package org.dding.mvc;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.dding.mvc.annotation.ActionMethod;
import org.dding.mvc.validate.ValidateException;

/**
 * Page Context 存储了用来填充 template的 数据
 * 
 */
public class PageContext {

	// 页面跳转方式，foward/redirect
	private ActionMethod.ForwardMethod forwardMethod;

	// success or error view
	private String targetView;
	private ConcurrentHashMap<String, ValidateException> validateExceptions = new ConcurrentHashMap<String, ValidateException>();

	private ConcurrentHashMap<String, Object> resultMap = new ConcurrentHashMap<String, Object>();

	private Exception businessException = null;

	void setTargetMethod(ActionMethod.ForwardMethod forwardMethod) {
		this.forwardMethod = forwardMethod;
	}

	public ActionMethod.ForwardMethod getTargetMethod() {
		return forwardMethod;
	}

	public Map<String, Object> getResultMap() {
		// 不能返回 unmodifiedMap，因为 Velocity render过程中需要修改
		return resultMap;
	}

	public void setTargetView(String targetView) {
		this.targetView = targetView;
	}

	public String getTargeView() {
		return targetView;
	}

	public void setAttribute(String key, Object value) {
		if (value == null)
			return;
		resultMap.putIfAbsent(key, value);
	}

	public Object getAttribute(String key) {
		return resultMap.get(key);
	}

	public void addValidateException(ValidateException ve) {
		validateExceptions.putIfAbsent(ve.getInputField(), ve);
	}

	public boolean hasValidateException() {
		return !validateExceptions.isEmpty();
	}

	public void setBusinessException(Exception exception) {
		this.businessException = exception;
	}

	public boolean hasBusinessException() {
		return businessException != null;
	}

	public Exception getBusinessException() {
		return businessException;
	}

	public String getBusinessExceptionMessage() {
		StringWriter sw = new StringWriter();
		businessException.printStackTrace(new PrintWriter(sw));
		try {
			sw.close();
		} catch (Exception e) {
			// ignore
		}
		return sw.getBuffer().toString();
	}

	public Map<String, ValidateException> getValidateExceptions() {
		return Collections.unmodifiableMap(validateExceptions);
	}
}
